package com.cskaoyan.javase.oop3._3inner._4anonymous._0introduction;

/**
 * 匿名内部类，首先它是特殊的局部内部类，它的成员特点，访问特点和局部内部类都是一样的，所以不再赘述。
 *
 * 局部内部类在方法中的使用，用处很多，但它的语法过于复杂了，我们需要简化它，就需要匿名内部类
 * 匿名内部类指的是这个类没有名字，它是一个特殊的局部内部类。由于没有名字，它的语法也不可能是定义一个类
 *      所以匿名内部类的语法，直接就是new对象，跳过了定义类的过程，所以它比局部内部类要简洁很多。
 *      匿名内部类其实不是一个类，而是一个对象，所以准确的叫法是匿名内部类对象
 * 语法：
 *     new 类名/接口名(参数){
 *         // 表示类体
 *     }
 * 解释：
 *      1.new仍然表示创建对象，表示直接创建类名/接口名的子类对象（隐含了继承或者实现）。
 *      2.类名可以写普通类，也可以写抽象类
 *      3.参数是传给该对象父类类型（new后面写的类名）的构造方法的参数（只有类有构造方法，接口没有）
 *      4.这个匿名子类的类体
 *
 * 匿名内部类对象的使用:
 *      1.直接使用,因为它本身就表示一个对象,这时候它就相当于一个匿名对象.
 *      优点:
 *          a.快,方便简洁
 *          b.可以访问子类中独有的成员
 *     缺点:
 *          a.一次性的,不能多次使用
 *
 *     2.父类引用指向子类对象接收,然后使用
 *      优点:
 *          a.不是一次性对象了,可以多次使用
 *      缺点:
 *          a.首先没那么方便了.
 *          b.无法访问子类独有成员,而且是真的没法访问,强转不了
 *
 *
 *
 * @since 14:47
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        int a = 10;
        // 定义局部内部类
        class IAImpl implements IA {
            int a = 10;
            @Override
            public void test() {
                System.out.println("hello world!");
            }
        }
        test(new IAImpl());

        // 匿名内部类的用法
        test(new IA() {
            int a = 10;
            @Override
            public void test() {
                System.out.println("我比你高级啊,我是匿名内部类的用法!");
            }
        });


        new AbstractPerson() {
            @Override
            public void eat() {
                System.out.println("我今天晚上吃腊八粥!");
            }

            public void sleep() {
                System.out.println("除了吃就是睡,挣钱为了谁啊!");
            }
        }.sleep();


        AbstractPerson ap = new AbstractPerson() {
            @Override
            public void eat() {
                System.out.println("我今天晚上吃烤生蚝!");
            }

            public void sleep() {
                System.out.println("除了吃就是睡,挣钱为了谁啊!");
            }
        };
        ap.eat();
        // 无法强转
        // ((AbstractPerson) ap).sleep();

    }

    public static void test(IA ia) {
        ia.test();
    }
}

interface IA {
    void test();
}

abstract class AbstractPerson {
    public abstract void eat();
}
